import interActionEnum from "../enum/interAction.enum"
import componentEnum from "../enum/component.enum"
import PathTypeEnum from "../enum/pathType.enum"
import {
  ConfigureCommand,
  CreateNodeCommand,
  CreateNodesCommand,
  CreateObjectsCommand,
  DeserializeCommand,
  GetImageCommand,
  QueryCommand,
  RegisterCommand,
  RegisterComponentsCommand,
  SerializeCommand
} from "../command/scene.command"
import { DependencyFetcher, isNum } from "./utils"
import SceneModule from "../module/SceneModule"
export default {
  InteractionType: sdk => sdk.addEnumToInterface({ namespace: "Scene", name: "InteractionType", values: interActionEnum }),
  Component: sdk => sdk.addEnumToInterface({ namespace: "Scene", name: "Component", values: componentEnum }),
  PathType: sdk => sdk.addEnumToInterface({ namespace: "Scene", name: "PathType", values: PathTypeEnum }),
  register: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(RegisterCommand, async e => {
      const [t] = await dependencies.getDependencies()
      return t.registerFactory(e.name, e.factory)
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "register", args: ["name", "factory"] }, e => new RegisterCommand(e))
    dependencies.getDependencies().then(([t]) => {
      sdk.addEnumToInterface({ namespace: "Scene", name: "Component", values: t.componentMap() })
    })
  },
  createNode: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(CreateNodeCommand, async () => {
      const [e] = await dependencies.getDependencies()
      return e.createNode()
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "createNode", args: ["userContext"] }, e => new CreateNodeCommand(e))
  },
  createNodes: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(CreateNodesCommand, async e => {
      if (!isNum(e.count)) throw Error("count is not a valid number")
      const [t] = await dependencies.getDependencies(),
        n = []
      for (let o = 0; o < e.count; o++) n.push(t.createNode())
      return n
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "createNodes", args: ["count", "userContext"] }, e => new CreateNodesCommand(e))
  },
  query: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(QueryCommand, async e => {
      const [t] = await dependencies.getDependencies()
      return t.sceneTags().getObjects(e.tags)
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "query", args: ["tags"] }, e => new QueryCommand(e))
  },
  configure: (sdk, THREE, allFunc, dependencies) => {
    dependencies.getDependencies().then(([e]) => {
      allFunc.addBinding(ConfigureCommand, async o => {
        o.callback(e.cwfRenderer.renderer, THREE, e.getScene().effectComposer)
      })
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "configure", args: ["callback"] }, e => new ConfigureCommand(e))
  },
  getImage: (sdk, allFunc, dependencies) => {
    dependencies.getDependencies().then(([e]) => {
      allFunc.addBinding(GetImageCommand, async t => e.getSignedUrls().getImageBitmap(t.path, t.width, t.height, t.options))
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "getImage", args: ["path", "width", "height", "options"] }, e => new GetImageCommand(e))
  },
  deserialize: (sdk, allFunc, dependencies: DependencyFetcher<[Promise<SceneModule>]>) => {
    allFunc.addBinding(DeserializeCommand, async e => {
      const [t] = await dependencies.getDependencies()
      return t.deserialize(e.text)
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "deserialize", args: ["text"] }, e => new DeserializeCommand(e))
  },
  serialize: (sdk, allFunc, dependencies: DependencyFetcher<[Promise<SceneModule>]>) => {
    allFunc.addBinding(SerializeCommand, async e => {
      const [t] = await dependencies.getDependencies()
      return t.serialize(e.objects)
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "serialize", args: ["objects"] }, e => new SerializeCommand(e))
  },
  registerComponents: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(RegisterComponentsCommand, async e => {
      const [t] = await dependencies.getDependencies()
      if (!Array.isArray(e.components)) throw Error("components must be an array")
      for (const o of e.components) t.registerFactory(o.name, o.factory)
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "registerComponents", args: ["components"] }, e => new RegisterComponentsCommand(e))
  },
  createObjects: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(CreateObjectsCommand, async e => {
      if (!isNum(e.count)) throw Error("count is not a valid number")
      const [t] = await dependencies.getDependencies(),
        n = []
      for (let o = 0; o < e.count; o++) n.push(t.createObject())
      return n
    })
    sdk.addCommandCreator({ namespace: "Scene", name: "createObjects", args: ["count"] }, e => new CreateObjectsCommand(e))
  },
  SourceType: () => {}
}
